package com.dxtan90.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;

/**
 * 异步任务创建
 *
 * @author shijunhao
 * @since 2023-10-08
 */
public class SyncMission {
    public SyncMission(SyncMissionBuilder builder) {
        this.executor = builder.executor;
    }

    //当前所需要执行的任务
    private final List<CompletableFuture<String>> mission = new ArrayList<>();
    //当前线程池
    private final ExecutorService executor;

    /**
     * 添加任务
     *
     * @param runnable runnable
     */
    public void addMission(Runnable runnable) {
        Supplier<String> supplier = () -> {
            runnable.run();
            return "SUCCESS";
        };
        addMission(supplier);
    }

    /**
     * 添加任务
     *
     * @param supplier supplier
     */
    public void addMission(Supplier<String> supplier) {
        CompletableFuture<String> future;
        if (Objects.isNull(executor)) {
            future = CompletableFuture.supplyAsync(supplier);
        } else {
            future = CompletableFuture.supplyAsync(supplier, executor);
        }
        mission.add(future);
    }

    /**
     * 添加任务 等待所有结束
     */
    public void waitAllOf() {
        CompletableFuture.allOf(mission.toArray(new CompletableFuture[]{})).join();
        destroy();
    }

    /**
     * 添加任务 等待任何一个结束
     */
    public void waitAnyOf() {
        CompletableFuture.anyOf(mission.toArray(new CompletableFuture[]{})).join();
        destroy();
    }


    /**
     * 销毁函数 结束关闭线程池
     */
    private void destroy() {
        if (this.executor != null) {
            this.executor.shutdown();
        }
    }

    /**
     * 异步任务构建Builder
     */
    public static class SyncMissionBuilder {
        private ExecutorService executor;

        public SyncMissionBuilder executor(ExecutorService executor) {
            this.executor = executor;
            return this;
        }

        public SyncMission build() {
            return new SyncMission(this);
        }
    }
}
